package com.jjb.spider.common.bootstaeap;

import com.jjb.spider.mqtt.net.NettyContentService;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.buffer.PooledByteBufAllocator;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.mqtt.MqttDecoder;
import io.netty.handler.codec.mqtt.MqttEncoder;
import io.netty.handler.timeout.IdleStateHandler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.concurrent.TimeUnit;

public abstract class AbstractBootstrapServer {

    protected Logger log  = LoggerFactory.getLogger(NettyContentService.class);

    private ServerBootstrap bootstrap = null;
    private  ChannelFuture channelFuture = null;
    public void startup() throws Exception{
        NioEventLoopGroup bossGroup = new NioEventLoopGroup();
        NioEventLoopGroup workGroup = new NioEventLoopGroup();
        bootstrap = new ServerBootstrap();

        bootstrap.group(bossGroup, workGroup);
        bootstrap.channel(NioServerSocketChannel.class);

        bootstrap
                //如果客户端在创建连接时，操作1秒仍未创建则关闭连接
                .option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 1000)

                //服务器收到客户端请求数据后超过2秒仍未处理则超时
                .option(ChannelOption.SO_TIMEOUT, 2000)
                //netty收到较小的数据包是否延迟发送，开启可提升性能
                .option(ChannelOption.TCP_NODELAY, false)
                //临时存放处理完成3次握手的队列，不设置使用Java默认值50
                .option(ChannelOption.SO_BACKLOG , 256)
                //不允许重复绑定端口
                .option(ChannelOption.SO_REUSEADDR, true)
                //开启TCP协议的探测心跳检测
                .option(ChannelOption.SO_KEEPALIVE, true)

                .option(ChannelOption.ALLOCATOR, PooledByteBufAllocator.DEFAULT);

                //设置接受数据缓冲的大小
                //.option(ChannelOption.SO_RCVBUF, 10485760);

        bootstrap.childOption(ChannelOption.TCP_NODELAY, true)
                .childOption(ChannelOption.SO_KEEPALIVE, true)
                .childOption(ChannelOption.ALLOCATOR, PooledByteBufAllocator.DEFAULT);

        bootstrap.childHandler(new ChannelInitializer<SocketChannel>() {
            @Override
            protected void initChannel(SocketChannel socketChannel) throws Exception {
                ChannelPipeline channelPipeline = socketChannel.pipeline();
                initChannelPipelineLast(channelPipeline);
            }

        });

        int port = port();
        channelFuture = bootstrap.bind(port).sync();
        if(channelFuture.isSuccess()){
            log.info("mqtt startup success port = " + port);
            //channelFuture.channel().closeFuture().sync();
        } else {
            log.error("mqtt startup fail port = {}",  port);

        }
    }

    public abstract void initChannelPipelineLast(ChannelPipeline channelPipeline);

    public abstract int port() ;

    protected void close() {
        channelFuture.channel().close();
    }
}
